// 这个一个使用opendir,readdir和closedir等对目录操作的函数
// 该程序显示的是目录中包含的文件名，其实这个目录的路径名被作为命令行参数传送
// note:ls命令会按照字母顺序对文件名进行排序，而readdir函数则按照起在目录文件中出现的顺序显示文件名
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>

int printDir (char *path) {
    DIR *dr;
    int ret;
    struct dirent *direntp;
    struct stat statbuf;    // struct stat 用来保存stat和lstat函数中返回的信息
    // note: 如果statbuf使用指针，则需要使用malloc函数为其分配内存空间，不如直接使用statbuf（不加指针）方便

    // 使用opendir函数打开所指定的目录
    dr = opendir(path);
    if(dr == NULL) {
        perror("Failed to open directory");
        return -1;
    } else {
        printf("the directory open successful!\n");
    }

    // 打印目录中的文件
    while ( (direntp = readdir(dr)) != NULL) {
        // fprintf(stderr, "打印文件： ");
        fprintf(stderr, "%s", direntp->d_name);

        // 补全路径名，否则无法访问
        char buf[256] = {0};
        sprintf(buf, "%s/%s", path, direntp->d_name);

        // 调用stat函数查看文件的状态
        /* 在该函数中，stat只能访问用户所在的当前目录-->是路径的问题, 需要绝对路径才可以访问*/
        ret = stat(buf, &statbuf);
        if (ret == -1) {
            perror(" : Failed to get file status");
            //return -1;
        } else {
            // 其中st_atim表示最后一次访问的时间，st_time表示最后一次数据修改的时间
            // st_ctime表示最后一次文件状态改变的时间
            // ctime返回的字符串会以换行符结束，因此可以不用\n
            fprintf(stderr," : last accessed at %s", ctime(&statbuf.st_atim) );

            // 如果该文件是个目录，则递归打印目录中的文件
            if (*direntp->d_name != '.' && S_ISDIR(statbuf.st_mode)) {
                
                // 当递归打印目录的时候，需要指定绝对路径，此时为 ./test
                //sprintf(buf + strlen(buf), "/%s", direntp->d_name);

                printf("***************************%s is directory!***********\n", buf);

                printDir(buf);

                printf("***************************%s ********************\n", buf);
            }
        }

    }
    while (direntp == NULL && errno == EINTR);

    // note:使用完毕后一定要关闭目录
    closedir(dr);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s dir\n", argv[1]);
        return -1;
    }

    int ret = printDir(argv[1]);

    return ret;
}
